/*
*  Project Name  :    PokerFace
*  File Name     :    Gui.pde
*  Description   :    This is the GUI for PokerFace, it handles displaying the game state and taking
*                     user input for various actions/stages of the poker game.
*  Written By    :    Luis Cordon Jr
*                     Juan Cruz
*                     James Latief
*  Date          :    11/26/12
*/

//Libraries used
import controlP5.*;
import oscP5.*;
import netP5.*;
import java.awt.image.*; 
import javax.imageio.*;
import processing.video.*;


//Global Variables
final int winWidth = 1024, winHeight = 768;
PImage pokerTable, cardOne, cardTwo;
PImage video;
PImage commCardOne, commCardTwo, commCardThree, commCardFour, commCardFive;
String path, cardOneName, cardTwoName;
String commCardOneName, commCardTwoName, commCardThreeName, commCardFourName, commCardFiveName;
boolean playerOption = true, loggedIn = false;
String pot = "", player = "", chipstack = "", bet = "";
String history = "", player2 = "", chipstack2 = "";
String winner = "";
ArrayList cards;
boolean fullScreen = false;
byte[] buffer = new byte[65536]; 
/***************************/
// This is the port we are sending to
int clientPort = 9100;  // corresponds to portFirst in server

// This is our object that sends UDP out
DatagramSocket ds;   //sends

// Capture object
Capture cam;
/***************************/



//Global Objects
Textarea myTextarea;
Textlabel potsize, potsizeAmt;
ControlP5 cp5, login, tableInfo;
OscP5 oscP5;
NetAddress myRemoteLocation;
OscMessage myMessage;

//Variables for displaying buttons
int padding = 10;

int startX = (winWidth  * 3) / 4;
int startY = (winHeight * 3) / 4;

int boxWidth  = winWidth / 4;
int boxHeight = winHeight / 4;

int buttonWidth     =  (boxWidth - (padding * 4)) / 3;
int buttonHeight    =  boxHeight / 4;
int buttonPositionX =  startX + (padding * 6);
int buttonPositionY =  startY + (boxHeight / 2) - 90;



/*
*  The function setup() initializes the GUI and sets it up to be run with a server
*/
void setup()
{
  size(winWidth, winHeight);                      
  frameRate(30);
  oscP5 = new OscP5(this, 12333);

  path = sketchPath;
  path = path + "/data/pictures";
  
  

  video = createImage(400,400,RGB);
  try
  {
    pokerTable = loadImage(path + "/pokerTable.png");
  }
  catch(Exception e)
  {
    println("Failed to load pokerTable. Try again"); 
    System.exit(0);
  }

  cp5 = new ControlP5(this);
  login = new ControlP5(this);
  tableInfo = new ControlP5(this);

  reset();
  inputButtons();
  setupHistory();
  loginForm();

  myRemoteLocation = new NetAddress("130.212.133.244", 12222);
  
   /****************/
   try {
    ds = new DatagramSocket();
  } catch (SocketException e) {
    e.printStackTrace();
  } // Initialize Camera
  
  
  cam = new Capture( this, 400,400,40);

  /****************/
}

/*
*  The function draw() draws the GUI and its multiple states
*/

void captureEvent( Capture c ) {
  c.read();
  // Whenever we get a new image, send it!
  broadcast(c);
}
void broadcast(PImage img) {

  // We need a buffered image to do the JPG encoding
  BufferedImage bimg = new BufferedImage( img.width,img.height, BufferedImage.TYPE_INT_RGB );

  // Transfer pixels from localFrame to the BufferedImage
  img.loadPixels();
  bimg.setRGB( 0, 0, img.width, img.height, img.pixels, 0, img.width);

  // Need these output streams to get image as bytes for UDP communication
  ByteArrayOutputStream baStream	= new ByteArrayOutputStream();
  BufferedOutputStream bos		= new BufferedOutputStream(baStream);

  // Turn the BufferedImage into a JPG and put it in the BufferedOutputStream
  // Requires try/catch
  try {
    ImageIO.write(bimg, "jpg", bos);
  } 
  catch (IOException e) {
    e.printStackTrace();
  }

  // Get the byte array, which we will send out via UDP!
  byte[] packet = baStream.toByteArray();

  // Send JPEG data as a datagram
  println("Sending datagram with " + packet.length + " bytes"); // 130.212.133.244
  try {
    ds.send(new DatagramPacket(packet,packet.length, InetAddress.getByName("130.212.133.244"),clientPort));
  } 
  catch (Exception e) {
    e.printStackTrace();
  }
}
/*******************/
void draw()
{
  if (loggedIn) {
    image(pokerTable, 0, 0, winWidth, winHeight);
    if (playerOption)
    {
      regularOption();
    }  
    drawSeats();

    //displays player cards
    if (cardOneName.length() > 1 && cardTwoName.length() > 1) {
      cardOne = loadImage(path + "/" + cardOneName + ".gif");
      cardTwo = loadImage(path + "/" + cardTwoName + ".gif");
      image(cardOne, 425, 620);
      image(cardTwo, 525, 620);
    }
      if(fullScreen){
        drawFullScreen();
      }else{
        drawSeats();
      }




    //displays community cards
    if (commCardOneName.length() > 1) {
      commCardOne = loadImage(path + "/" + commCardOneName + ".gif");
      commCardTwo = loadImage(path + "/" + commCardTwoName + ".gif");
      commCardThree = loadImage(path + "/" + commCardThreeName + ".gif");
      image(commCardOne, 300, 230);
      image(commCardTwo, 380, 230);
      image(commCardThree, 460, 230);
    }
    if (commCardFourName.length() > 1) {
      commCardFour = loadImage(path + "/" + commCardFourName + ".gif");
      image(commCardFour, 540, 230);
    }
    if (commCardFiveName.length() > 1) {
      commCardFive = loadImage(path + "/" + commCardFiveName + ".gif");
      image(commCardFive, 620, 230);
    }

    //display pot size
    fill(255);
    text("Pot size", 440, 190);
    text("$ " + pot, 440, 220);

   myTextarea.setText(history);
  }
}

public void oscEvent(OscMessage theOscMessage) {
  String temp = theOscMessage.toString();
  if (temp.contains("community")) {
    displayCommunityCards(temp);
  } 
  else if (temp.contains("potsize")) {
    setPotsize(temp);
  } 
  else if (temp.contains("winner")) {
    winner(temp);
  }
  else if(temp.contains("act")) {
    if(temp.contains(player)) {
      act(temp);
    }
  }
  else if(temp.contains("chipstack")) {
    chipstack(temp);
  }
  else if(temp.contains("holeCards")) {
    if(temp.contains(player)) {
      displayHoleCards(temp);
    }
  }
  else if(temp.contains("move")) {
    playerMove(temp);
  }else if(temp.contains("reset"))
        reset();
}

public void playerMove(String msg) {
  int index = msg.indexOf("-");
  String act = msg.substring(index + 1, msg.length() - 1);
  act = act.replace("-", " ");
  history += act + "\n";
  myTextarea.setText(history);
}

public void displayHoleCards(String msg) {
   int index = msg.indexOf("-");
   index = msg.indexOf("-", index + 1);
   int index2 = msg.lastIndexOf("-");
   cardOneName = msg.substring(index + 1, index2);
   cardTwoName = msg.substring(index2 + 1, msg.length() - 1);
}

public void winner(String msg) {
  int index = msg.indexOf("-");
  String theWinner = msg.substring(index + 1, msg.length() - 1);
  history += theWinner + " won $" + pot + "\n";
  myTextarea.setText(history);
  //reset();
}

public void chipstack(String msg) {
  int index = msg.lastIndexOf("-");
  String chipStk = msg.substring(index + 1, msg.length() - 1);
  if(msg.contains(player)) {
    chipstack = chipStk;
  }
  else {
    chipstack2 = chipStk;
  }
}

public void act(String msg) {
  if(msg.contains(player)) {
    cp5.show();
  }
}

public void setPotsize(String msg) {
  //println(msg);
  int index = 0;
  //get location of dash in message
  index = msg.indexOf("-", 0);
  pot = msg.substring(index + 1, msg.length() - 1);
}

public void reset() {
  cardOneName = "";
  cardTwoName = "";
  commCardOneName = "";
  commCardTwoName = "";
  commCardThreeName = "";
  commCardFourName = "";
  commCardFiveName = "";
  pot = ""; 
}

public void displayCommunityCards(String msg) {
  boolean done = false;
  int index = 0, index2 = 0;
  while (!done) {
    index = msg.indexOf("-", 0);
    //parse out only cards
    String cards = msg.substring(index + 1, msg.length() - 1);
    //get index of first dash and parse out first card
    index = cards.indexOf("-", 0);
    commCardOneName = cards.substring(0, index);
    //get index of next dash and parse out second card
    index2 = cards.indexOf("-", index + 1);
    commCardTwoName = cards.substring(index + 1, index2);
    //get index of next dash and parse out third card
    index = index2;
    index2 = cards.indexOf("-", index + 1);
    
    //check if last card parsed
    if (index2 < 0) {
      commCardThreeName = cards.substring(index + 1, cards.length());
      break;
    } 
    else {
      commCardThreeName = cards.substring(index + 1, index2);
    }
    
    //get index of next dash and parse out fourth card
    index = index2;
    index2 = cards.indexOf("-", index + 1);
    //check if last card parsed
    if (index2 < 0) {
      commCardFourName = cards.substring(index + 1, cards.length());
      break;
    } 
    else {
      commCardFourName = cards.substring(index + 1, index2);
    }
    
    //get index of next dash and parse out fifth card
    index = index2;
    index2 = cards.indexOf("-", index + 1);
    //check if last card parsed
    if (index2 < 0) {
      commCardFiveName = cards.substring(index + 1, cards.length());
      break;
    } 
    else {
      commCardFiveName = cards.substring(index + 1, index2);
    }
  }
}

//login form for start of program
public void login() {
  player = (login.get(Textfield.class, "name").getText());
  chipstack = (login.get(Textfield.class, "buyIn").getText());
  float chips = parseFloat(chipstack);
  if(player.length() > 0 && chips > 1000.0f && chips < 3000000.0f) {
    loggedIn = true;
    login.hide();
    myTextarea.show();
    myMessage = new OscMessage("login-" + player + "-" + chipstack);
    oscP5.send(myMessage, myRemoteLocation);
  }
}

//buttons for user action
public void call() {
  myMessage = new OscMessage(player + "-call");
  oscP5.send(myMessage, myRemoteLocation);
  cp5.hide();
}

public void check() {
  myMessage = new OscMessage(player + "-check");
  oscP5.send(myMessage, myRemoteLocation);
  cp5.hide();
}

public void bet() {
  bet = (cp5.get(Textfield.class, "amount").getText());
  float betAmount = new Float(bet);
  float chips = new Float(chipstack);
  if (betAmount > 0 && betAmount <= chips) {
    myMessage = new OscMessage(player + "-bet-" + bet);
    oscP5.send(myMessage, myRemoteLocation);
    cp5.get(Textfield.class, "amount").clear();
    cp5.hide();
  }
}

public void fold() {
  myMessage = new OscMessage(player + "-fold");
  oscP5.send(myMessage, myRemoteLocation);
  cp5.hide();
}

public void regularOption()
{ 
  textSize(32);
  text(player + "'s Options", buttonPositionX-60, buttonPositionY-padding-20);
  fill(300);
}

public void inputButtons()
{
  PFont font = createFont("arial", 20);

  //Call button
  cp5.addButton("call")
    .setPosition(buttonPositionX - (buttonWidth + padding), buttonPositionY)
      .setSize(buttonWidth, buttonHeight)
        ;
  cp5.getController("call")
    .getCaptionLabel()
      .setFont(font)
        .toUpperCase(true)
          .setSize(24)
            ;  

  //Check button
  cp5.addButton("check")
    .setPosition(buttonPositionX, buttonPositionY)
      .setSize(buttonWidth + 20, buttonHeight)
        ;
  cp5.getController("check")
    .getCaptionLabel()
      .setFont(font)
        .toUpperCase(true)
          .setSize(24)
            ;  

  //Fold button
  cp5.addButton("fold")
    .setPosition((buttonPositionX + (buttonWidth + 20) + padding), buttonPositionY)
      .setSize(buttonWidth, buttonHeight)
        ;
  cp5.getController("fold")
    .getCaptionLabel()
      .setFont(font)
        .toUpperCase(true)
          .setSize(24)
            ;  

  //Bet button
  cp5.addButton("bet")
    .setPosition(buttonPositionX - 25, buttonPositionY + 55)
      .setSize(buttonWidth - 15, buttonHeight)
        ;
  cp5.getController("bet")
    .getCaptionLabel()
      .setFont(font)
        .toUpperCase(true)
          .setSize(24)
            ;  

  cp5.addTextfield("amount")
    .setPosition(buttonPositionX + (padding * 4.5), buttonPositionY + 55)
      .setSize(buttonWidth, buttonHeight)
        .setFont(font)
          .setColor(color(255))            
            .setCaptionLabel("")
              ;   
  cp5.getTooltip().setDelay(0);             
  cp5.getTooltip().register("amount", "Enter amount to bet");                
  cp5.getTooltip().setWidth(50);
  cp5.hide();
}

public void setupHistory()
{  
  myTextarea = tableInfo.addTextarea("txt")
    .setPosition(25, (winHeight * 5 ) / 7)
      .setSize(200, 200)
        .setFont(createFont("arial", 18))
          .setLineHeight(20)
            .setColor(color(0))
              .setColorBackground(128)
                .showScrollbar()
              ;
  myTextarea.hide();                
}

public void loginForm() {
  Textlabel programName, maxBuyIn, minBuyIn;
  PFont temp = createFont("Arial", 20, true);
  ControlFont buttonFont = new ControlFont(temp, 27);
  if (!loggedIn) {
    background(0);
    fill(128);
    rect(300, 100, 400, 600);

    //display welcome message
    fill(255);
    textSize(30);
    text("WELCOME TO POKERFACE", 310, 140);

    //display messages about logging in
    fill(0);
    textSize(25);
    text("Max Buy-in : $3,000,000", 325, 225);
    text("Min  Buy-in : $1,000", 325, 250);

    textSize(20);

    //display input fields
    text("Enter name:", 325, 350);
    login.addTextfield("name")
      .setPosition(325, 360)
        .setSize(350, 50)
          .setFont(createFont("arial", 20))
            .setColor(255)
              .setCaptionLabel("")
                ;    
    text("How much would you like to buy-in?", 325, 450);
    login.addTextfield("buyIn")
      .setPosition(325, 460)
        .setSize(350, 50)
          .setFont(createFont("arial", 20))
            .setColor(255)
              .setCaptionLabel("")
                ;

    //add login button
    login.addButton("login")
      .setPosition(550, 600)
        .setSize(100, 50)
          .captionLabel().setControlFont(buttonFont)
            ;
  }
}
public void drawFullScreen()
{
 image(cam,320,120);
  
}
public void drawSeats()
{
  int bwidth = winWidth/8;
  int space = padding + bwidth;
  int STARTY = winHeight/4;
  int BASE = winWidth/8;

  //draw player in seat one
  fill(255);
  textSize(20);
  text(player, 50, 180);
  fill(127, 210, 55);
  image(cam,padding,STARTY, BASE, BASE);
  fill(255);
  textSize(20);
  text("Chips:", 20, 350);
  text("$ " + chipstack, 20, 380);
  
  //draw player in seat two
  fill(127, 210, 55);
  image(cam,winWidth-BASE-10, STARTY, BASE, BASE);
  fill(255);
  textSize(20);
  text("Chips:", 900, 350);
  text("$ " + chipstack2, 900, 380);
}


